# 功能模块：产线级，主页面入口
# 作者：dl
# 描述：产线级业务逻辑入口

import os
import vtk
from trame.app import asynchronous
import datetime
import asyncio
from gltf import GLTFLoader, GLTFRenderEngine
import random

from visualizationCom.tools.color import hex_to_rgba
from visualizationCom.splitWindow import Window


class productlineScene:
    # 构造函数
    def __init__(self, parent, webState, webCtrl):

        self.parent = parent
        self.webState = webState
        self.webCtrl = webCtrl

        # 动画启动标志
        self.animationFlag = False

        self.splitRenderWindow = Window(self, webState, webCtrl)
        self.splitScene = self.splitRenderWindow.LoadModel(
            "model/device/device_scene.glb")

        self.animationListFlag = [] # 动画运行标记
        for item in self.splitScene.animations:
            self.animationListFlag.append(False)

        self.hasLoadScene = False  # 用于判断是否存在缓存

        self.engine = GLTFRenderEngine()
        self.renderer = self.engine.GetDefaultRenderer()
        self.renderer.SetGround(1, scale=5)
        self.camera = self.engine.GetCamera()

        self.renderer.SetUseFXAA(1)
        bg_color = hex_to_rgba('#132c4a')
        # bg_color = hex_to_rgba('#132c4a')
        self.renderer.SetBackground(bg_color[0], bg_color[1], bg_color[2])

        self.sceneList = []

        self.materialColorList = []  # 记录模型各个零部件材质原来的颜色

        # 定义相机初始化位置，用于重置
        self.initial_position = 0
        self.initial_focal_point = 0
        self.initial_view_up = 0

        self.light = vtk.vtkLight()

        self.healthDegreeColor = ['#f95959', '#f67280', '#f33535',
                                  '#f6fcae', '#ffc300', '#f9ed69', '#9df3c4', '#62d2a2', '#1fab89']

    def enterScene(self, firstRun):

        self.parent.mouseInteractorEvent.outline.Clear()
        self.parent.mouseInteractorEvent.lastPick = None

        self.renderer.SetActiveCamera(self.camera)
        with self.webState:
            self.webState.sceneKey = 'productline'

        self.parent.currentRenderer = self.renderer

        # 暂时写死模型
        if self.hasLoadScene == False:
            camera = self.camera
            self.initial_position = camera.GetPosition()
            self.initial_focal_point = camera.GetFocalPoint()
            self.initial_view_up = camera.GetViewUp()

            CURRENT_DIRECTORY = os.path.dirname(
                os.path.dirname(os.path.dirname(__file__)))

            modePath = "model/productionline/product_line.glb"

            # 结合 CURRENT_DIRECTORY 和 modePath 形成新的地址
            new_directory = os.path.join(CURRENT_DIRECTORY, modePath)
            self.load_file(new_directory)

        self.animationFlag = True
        self.UpdateAnimation(0, 0) # 第一次动画启动很慢，在未修复这个bug之前先这么写
        # self.async_animation()
        self.hasLoadScene = True

        self.parent.renderWindow.AddRenderer(self.renderer)

        # 重置交互器
        self.engine.SetRenderWindow(self.parent.renderWindow)
        self.parent.mouseInteractorEvent.SetDefaultRenderer(self.renderer)
        self.parent.mouseInteractorEvent.SetOutlineRenderer(
            self.engine.GetOutlineRenderer())

        self.restCamera()

        with self.webState:
            self.webState.renderViewStyle = {
                "position": "absolute", "width": "64vw", "height": "100%", "left": "0", "z-index": "1"}
            self.webState.renderSpiltViewStyle = {
                "position": "absolute", "width": "35vw", "height": "33%", "top": "0", "right": "0", "z-index": "1"}

        # self.async_animation()

        if firstRun != True:
            self.webCtrl.sendMsgToParent(
                {"eventScene": "productline", "eventName": "enterScene", "value": "complete"})

    def leaveScene(self):
        self.resetHealthDegree()
        self.parent.renderWindow.RemoveRenderer(self.renderer)
        self.animationFlag = False
        with self.webState:
            self.webState.renderViewStyle = {
                "display": "block", "height": "100%", "width": "100%", "position": "absolute"}
            self.webState.renderSpiltViewStyle = {"display": "none"}

    def load_file(self, file_name):
        self.renderer.RemoveAllViewProps()

        self.reader = GLTFLoader()
        self.reader.Load(file_name)
        scene = self.reader.GetScene()
        self.renderer.AddScene(scene)
        self.sceneList.append(scene)

        self.reader_detail_two = GLTFLoader()
        self.reader_detail_two.Load(file_name)
        scene_two = self.reader_detail_two.GetScene()
        scene_two.transform.Translate(1, 0, 0)
        self.renderer.AddScene(scene_two)
        self.sceneList.append(scene_two)

        self.reader_detail_three = GLTFLoader()
        self.reader_detail_three.Load(file_name)
        scene_three = self.reader_detail_two.GetScene()
        scene_three.transform.Translate(-1, 0, 0)
        self.renderer.AddScene(scene_three)
        self.sceneList.append(scene_three)

        # 记录颜色的数组用二维数组
        self.materialColorList = [[]]

    def showHealthDegree(self):
        for scene in self.sceneList:
            for node in scene.nodes:
                if len(node.meshes) > 0:
                    random_integer = random.randint(0, 8)
                    temp = hex_to_rgba(self.healthDegreeColor[random_integer])
                    color = [temp[0], temp[1], temp[2]]
                    self.engine.Highlight(scene, node, color, opacity=0.7)

        self.webCtrl.view_update()  # 必须更新两次，否则3d页面不会刷新
        self.webCtrl.view_update()
        self.webCtrl.view_update()

    def resetHealthDegree(self):
        self.engine.ClearHighlight()
        self.webCtrl.view_update()  # 必须更新两次，否则3d页面不会刷新
        self.webCtrl.view_update()

    @asynchronous.task
    async def async_animation_old(self):
        # check animation
        if self.animationFlag == False:
            self.splitScene.SetActiveAnimation(-1)
            print("stop animation")
            return

        print("start animation")
        self.splitScene.SetActiveAnimation(0)
        start = datetime.datetime.now()
        lastUpdate = start
        while self.animationFlag:
            lastUpdate = datetime.datetime.now()
            t = (lastUpdate - start).total_seconds()
            self.splitScene.UpdateAnimation(t)
            self.splitRenderWindow.UpdateView()
            self.webCtrl.view_split_update()
            while (datetime.datetime.now()-lastUpdate).total_seconds() < 0.1:
                await asyncio.sleep(0.001)

    @asynchronous.task
    async def async_animation(self):
        print("start animation")
        start = datetime.datetime.now()
        lastUpdate = start
        while self.animationFlag:
            lastUpdate = datetime.datetime.now()
            t = (lastUpdate - start).total_seconds()
            self.splitScene.UpdateAnimation(0, t)
            self.splitRenderWindow.UpdateView()
            self.webCtrl.view_split_update()
            while (datetime.datetime.now()-lastUpdate).total_seconds() < 0.1:
                await asyncio.sleep(0.001)

    @asynchronous.task
    async def command(self,index):
        activeAnimation = self.splitScene.animations[index]

        # 下面这段代码是用于终止当前正在运行的动画
        if self.animationListFlag[index]:
            self.animationListFlag[index] = False
            await asyncio.sleep(0.001)
            self.command(index)
        else:
            self.animationListFlag[index] = True

        if activeAnimation:
            t0 = activeAnimation.GetStartTime()
            t1 = activeAnimation.GetEndTime()
            am_duration = t1 - t0 #动画持续时长
            start = datetime.datetime.now()

            while self.animationFlag and self.animationListFlag[index]:
                now = datetime.datetime.now()
                t = (now - start).total_seconds()
                self.webCtrl.view_split_update()

                self.UpdateAnimation(index, t)

                await asyncio.sleep(0.001)

                if t > am_duration:
                    self.UpdateAnimation(index, 0)
                    # 动画执行结束
                    print('动画执行结束')
                    break

    def UpdateAnimation(self, index, time):
        activeAnimation = self.splitScene.animations[index]
        activeAnimation.SetAnimationTime(time)
        self.splitScene.Update()

    def restCamera(self):
        # 获取当前相机
        camera = self.renderer.GetActiveCamera()

        # 重置相机的位置和方向为初始状态
        # camera.SetPosition(self.initial_position)
        # camera.SetFocalPoint(self.initial_focal_point)
        # camera.SetViewUp(self.initial_view_up)
        # self.renderer.ResetCamera()
        camera.Dolly(0.2)
        camera.SetPosition(0.022862559081153838, 0.4663962052555386, 5.0)
        camera.SetFocalPoint(0.022862559081153838, 0.4663962052555386, 0.0)
        camera.SetViewUp(0.0, 1.0, 0.0)

    def changeEvn(self, bgIndex):
        if bgIndex == 1:
            # CURRENT_DIRECTORY = os.path.dirname(
            #     os.path.dirname(os.path.dirname(__file__)))

            # modePath = "3dENV/spaichingen_hill_1k.hdr"

            # # 结合 CURRENT_DIRECTORY 和 modePath 形成新的地址
            # new_directory = os.path.join(CURRENT_DIRECTORY, modePath)
            # self.renderer.SetEnvmap(new_directory)
            bg_color = hex_to_rgba('#041A21')
            self.renderer.SetBackground(bg_color[0], bg_color[1], bg_color[2])
        else:
            bg_color = hex_to_rgba('#132c4a')
            self.renderer.SetBackground(bg_color[0], bg_color[1], bg_color[2])
        self.parent.renderWindow.Render()
        self.webCtrl.view_update()
        self.webCtrl.view_update()
